package BNS.graphs;

import java.io.PrintStream;
import java.io.Serializable;
import java.util.Enumeration;


/** Bundles a Graph and its many graphlets into one unified package.
	*/
public class GraphPack implements Serializable {
	/**
   * 
   */
  private static final long serialVersionUID = 1L;
  /* TODO: This class is rather passive, in that its graphlets array is altered
			by other classes. It might make sense to involve it more in the creation 
			and maintenance of the graphlets. But beware of creating a huge or
			revealing class, since this has to be passed around to all the clients. 
			See GraphPackBuilder, which presently supplies creational functionality. 
			*/
//	public final AnnotatedGraph graph;
	public final Graph graph, graphlets[];
//	public final String comment;
	public final java.util.Properties properties;
	
	/** Constructor.
		@param gr the mother Graph 
		@param comment an arbitrary String intended only for humans,
			 to be stored with the GraphPack.
		*/
	public GraphPack(Graph gr, String comment) {
		graph= gr;
		graphlets= new Graph[graph.numNodes()];
//		this.comment= comment;
		properties= new java.util.Properties(); 
		properties.setProperty("comment",comment);
		}
	
	/** Retrieves the comment originally stored with this GraphPack. */
	public String toString() { return properties.getProperty("comment"); }
	
	/** Retrieves all the Properties and converts them to a printable form.
		*/
	public String getInfo() { 
		StringBuffer sb= new StringBuffer("");
		Enumeration<?> enu= properties.propertyNames();
		while (enu.hasMoreElements()) {
			String pname= (String)enu.nextElement();
			sb.append(pname+"="+properties.getProperty(pname)+"\n");
			}
		return sb.toString();
		}
	
	public Object getProperty(String pname) { return properties.getProperty(pname); }
	
	/** Returns the number of graphlets in this GraphPack. */
	public int size() { return graphlets.length; }
	
	/** dumps a lot of data, just for debugging */
	public void dump(PrintStream ps) {
		ps.println("dumping graphPack "+ getInfo());
		for (int gpi=0; gpi<size(); gpi++) {
			ps.println("graphlet["+gpi+"]= "+graphlets[gpi]);
			}
		}
/*
	public static void main(String[] args) {
		System.err.println("GraphPack startup "+ args.length +" args");
		if (args.length==0) {
			GraphPack gp= create();
			gp.graph.prettyPrint(System.err);
	//		new Library.putPack(null,gp);		// draws non-1.4 classes into compilations
			}
		else multiCreate(args);
		System.exit(0);
		}
		
	public static void multiCreate(String[] fnames) {
		JFrame frame= new JFrame("GraphPack Assembly Line");
		frame.setSize(900,800);
		Creator crPanel= new Creator();
		frame.setContentPane(crPanel);
		frame.validate();
		frame.setVisible(true);	// must come BEFORE init, so that getSize() works
		
		for (int fn=0; fn<fnames.length; fn++) {
			File gpFile= new File(fnames[fn]);
			AnnotatedGraph gr= MatrixGraph.create(gpFile); 
			if (gr==null) continue;
			gr.prettyPrint(System.err);
			String purpose= "NWLife";
			GraphPack gp= new GraphPack(gr, purpose);
			gp.buildLayouts(crPanel,2); 
			String gpName= gpFile.getName();
			gpFile= new File(gpName);
			Library.putPack(frame,gp,gpFile);
			}
		System.err.println("GraphPack obtained graph");
		frame.setVisible(false);
		frame.dispose();
		}
	
	public static GraphPack create() {
		GraphPack gp;
		JFrame frame= new JFrame("GraphPack Creation");
		frame.setSize(500,500);
		Creator crPanel= new Creator();
		frame.setContentPane(crPanel);
		frame.validate();
		frame.setVisible(true);	// must come BEFORE init, so that getSize() works
		
		Object[] options = 
			{"pre-built","Pref Attach", "Ring & Chords","Matrix"};	// arranged backwards on OSX!
		int modelID= JOptionPane.showOptionDialog(frame,
					"Pick a graph generator model...",	// prompt
					"Creating Graph",				// dialog title
					JOptionPane.YES_NO_OPTION,		// not used
					JOptionPane.QUESTION_MESSAGE,	// specifies icon
					null,		//don't use a custom Icon
					options,	//the titles of buttons
					null);		//default button title
		System.err.println("modelID="+ modelID);
		AnnotatedGraph gr= null;
		if (modelID== 3) gr= MatrixGraph.create(frame); 
		if (modelID== 2) gr= RingChordGraph.create(frame); 
		if (modelID== 1) gr= PrefAttachGraph.create(frame);
		if (modelID== 0) gp= Library.getPack(frame);
		else { 
			if (gr==null) return null;
			int extras= -1;
			try { extras= 2-JOptionPane.showConfirmDialog(frame,
							"Do you want neighbourhood edges too?",
							"viewtype", JOptionPane.YES_NO_OPTION); }
			catch(HeadlessException e) { throw new RuntimeException(e.getMessage()); }
			System.err.println("will build GraphPack, extras="+ extras);
			gp= new GraphPack(gr,"creation model: "+options[modelID]);
			gp.buildLayouts(crPanel,extras); 
			Library.putPack(frame,gp);
			}
		System.err.println("GraphPack obtained graph");
		frame.setVisible(false);
		frame.dispose();
		return gp;
		}
	
	private void buildLayouts(Creator crPanel, int extras) {
		try {
			crPanel.init(graph);
			System.err.println("GraphPack inited crPanel");
			synchronized(crPanel) { crPanel.wait();	}	// Creator's "next" button will kick this
			System.err.println("graphPack entering graphlet loop. extras="+ extras);
			Enumeration enNodes= graph.enumNodes();
//			for (int i=0; i<graph.numNodes(); i++) {
			while (enNodes.hasMoreElements()) {
				Node node= (Node)enNodes.nextElement();
				Graph graphlet= graph.makeGraphlet(node,extras);
				crPanel.init(graphlet);
				graphlet.prettyPrint(System.err);
				synchronized(crPanel) { crPanel.wait(); }// Creator's "next" button will kick this
				graphlets[node.getIndex()]= graphlet;
				}
			}
		catch(InterruptedException ie) {}
		}
*/	
	} // EOClass GraphPack
